﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EngineOfEvermore.Common;
using System.Drawing;

namespace EngineOfEvermore.Scene.Visual
{
    public delegate void CameraPositionChangedDelegate( Camera camera, Vector2d oldPosition, Vector2d newPosition );
    public delegate void CameraScaleChangedDelegate( Camera camera, float oldScale, float newScale );
    public delegate void CameraViewportSizeChangedDelegate( Camera camera, Size oldSize, Size newSize );

    public class Camera
    {
        Vector2d _position;
        float _scale = 1;
        Size _viewportSize = new Size( 640, 480 );
        SlimDX.Matrix _viewMatrix = SlimDX.Matrix.Identity;

        public event CameraPositionChangedDelegate PositionChanged;
        public event CameraScaleChangedDelegate ScaleChanged;
        public event CameraViewportSizeChangedDelegate ViewPortChanged;

        public void ApplyTransform() 
        {
            GraphicsExt.Instance.D3DObjects.Device.SetTransform(
                SlimDX.Direct3D9.TransformState.View,
                _viewMatrix 
                );
        }

        public Vector2d Position
        {
            get { return _position; }
            set 
            {
                if ( _position != value )
                {
                    Vector2d oldPosition = _position;

                    _position = value;
                    _updateMatrix();

                    if ( PositionChanged != null )
                    {
                        PositionChanged( this, oldPosition, _position );
                    }
                }
            }
        }

        public float Scale
        {
            get { return _scale; }
            set
            {
                if ( _scale != value )
                {
                    float oldScale = _scale;

                    _scale = value;
                    _updateMatrix();

                    if ( ScaleChanged != null )
                    {
                        ScaleChanged( this, oldScale, _scale );
                    }
                }
            }
        }

        public Size ViewportSize
        {
            get { return _viewportSize; }
            set 
            {
                if ( _viewportSize != value )
                {
                    Size oldSize = _viewportSize;

                    _viewportSize = value;
                    _updateMatrix();

                    if ( ViewPortChanged != null )
                    {
                        ViewPortChanged( this, oldSize, _viewportSize );
                    }
                }
            }
        }

        public RectangleF GetDisplayedArea()
        {
            float scaledViewportWidth = _viewportSize.Width / _scale;
            float scaledViewportHeight = _viewportSize.Height / _scale;

            RectangleF displayedArea = new RectangleF(
                _position.X - scaledViewportWidth * 0.5f,
                _position.Y - scaledViewportHeight * 0.5f, 
                scaledViewportWidth, 
                scaledViewportHeight
                );

            return displayedArea;
        }

        void _updateMatrix()
        {
            SlimDX.Matrix.Translation( -_position.X, -_position.Y, 0, out _viewMatrix );
            _viewMatrix *= SlimDX.Matrix.Scaling( _scale, _scale, 1 );
            _viewMatrix *= SlimDX.Matrix.Translation( _viewportSize.Width * 0.5f,
                                                      _viewportSize.Height * 0.5f,
                                                      0 );
        }
    }
}
